package main

import (
	"bytes"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"go.uber.org/zap"
	"gopkg.in/ini.v1"
	"io"
	"log"
	"net/http"
	"web_back_go/Common"
	"web_back_go/DAO/gorm"
	"web_back_go/Middleware"
	"web_back_go/Middleware/Log"
	"web_back_go/Router"
)

/*
getRequestBody
@description: 获取请求体,用在log上面
*/
func getRequestBody(c *gin.Context) string {
	// 设置最大请求体大小，防止内存溢出攻击
	const maxBodySize = 20 << 20 // 20MB
	if c.Request.ContentLength > int64(maxBodySize) {
		c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": "request body too large"})
		c.Abort()
		return ""
	}

	bodyBytes, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "failed to read request body"})
		c.Abort()
		return ""
	}

	// 将读取的内容重新设置回请求体
	c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

	return string(bodyBytes)
}
func main() {

	r := gin.Default()
	logger := Log.InitLoggerWithFile()
	defer func(logger *zap.Logger) {
		_ = logger.Sync()
	}(logger)
	//初始化minio
	Middleware.InitMinio()
	//初始cache
	Middleware.InitCache()
	//初始化xorm
	gorm.InitGormDB()
	//配置跨域
	config := cors.DefaultConfig()
	config.AllowOrigins = []string{"*"}
	config.AllowMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
	config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization"}
	config.AllowCredentials = true

	// 注册跨域中间件
	r.Use(cors.New(config))
	//全局错误拦截器
	r.Use(Middleware.RecoveryMiddleware())
	r.Use(func(c *gin.Context) {
		//path := c.Request.URL.Path

		_, username, _ := Common.CodeToken(c.GetHeader("Authorization"))
		if username == "" {
			username = "未登录"
		}
		logger.Info("request started",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("query", c.Request.URL.RawQuery),
			zap.String("body", getRequestBody(c)),
			zap.String("ip", c.RemoteIP()),
			zap.String("username", username),
		)
		c.Next()
	})
	Router.InitRouter(r)
	routes := r.Routes()
	routeCount := len(routes)
	log.Println("Total routes:", routeCount)

	//获取监听接口和地址
	cfg, err := ini.Load("./Config/config.ini")
	if err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}
	log.Println(cfg.Section("server_config").Key("host").String() + ":" + cfg.Section("server_config").Key("port").String())
	if err := r.Run(cfg.Section("server_config").Key("host").String() + ":" + cfg.Section("server_config").Key("port").String()); err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}
